package com.justonetech.springboot.utils;

import org.apache.commons.io.FilenameUtils;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * User: Chen Junping
 * Date: 12-3-22
 */
public class FileUtils {

    public static boolean exist(String fileName) {
        File file = new File(fileName);
        return file.exists();
    }

    public static boolean mkDirs(String dirName) {
        return exist(dirName) || new File(dirName).mkdirs();
    }

//    public static boolean copyFile(String sourceFileName, String destFileName) throws Exception {
//        File sourceFile = new File(sourceFileName);
//        File destFile = new File(destFileName);
//
//        FileInputStream fileInputStream = new FileInputStream(sourceFile);
//        FileOutputStream fileOutputStream = new FileOutputStream(destFile);
//        int i = IOUtils.copy(fileInputStream, fileOutputStream);
//        fileOutputStream.close();
//        fileInputStream.close();
//        return i > 0;
//    }
//
//    public static boolean moveFile(String sourceFileName, String destFileName) throws Exception {
//        boolean ret = copyFile(sourceFileName, destFileName);
//        if (ret) {
//            File sourceFile = new File(sourceFileName);
//            sourceFile.deleteOnExit();
//        }
//
//        return ret;
//    }

    /**
     * 文件下载 -- 断点续传
     *
     * @param request          request
     * @param response         response
     * @param filePath         文件路径
     * @param originalFileName 显示文件名
     * @throws Exception .
     */
    public static void downloadSection(HttpServletRequest request, HttpServletResponse response, String filePath, String originalFileName) throws Exception {
        File file = new File(filePath);
        if (!file.exists()) {
            response.sendError(404, "File not found!");
            return;
        }
        String fileName = file.getName();
        if (originalFileName != null) {
            fileName = originalFileName;
        }

        //判断不同浏览器分别设置header
        setDownloadContentType(request, response, fileName, null, false);

//        response.reset();
//        response.setCharacterEncoding("UTF-8");
        response.setHeader("Server", "justonetech");
        //告诉客户端允许断点续传多线程连接下载
        //响应的格式是: Accept-Ranges: bytes
        response.setHeader("Accept-Ranges", "bytes");

        InputStream fis = new FileInputStream(file);
        OutputStream fos = response.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        response.setContentLength((int) file.length());
        long p = 0;
        long l = file.length();

        //如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置
        //响应的格式是:
        //HTTP/1.1 200 OK
        //客户端请求的下载的文件块的开始字节
        if (request.getHeader("Range") != null) {
            //如果是下载文件的范围而不是全部,向客户端声明支持并开始文件块下载
            //要设置状态
            //响应的格式是:
            //HTTP/1.1 206 Partial Content
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206

            //从请求中得到开始的字节
            //请求的格式是:
            //Range: bytes=[文件块的开始字节]-
            p = Long.parseLong(request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-", ""));
        }

        //下载的文件(或块)长度
        //响应的格式是:
        //Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
        response.setHeader("Content-Length", new Long(l - p).toString());

        if (p != 0) {
            //不是从最开始下载,
            //响应的格式是:
            //Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
            response.setHeader("Content-Range", "bytes " + new Long(p).toString() + "-" + new Long(l - 1).toString() + "/" + new Long(l).toString());
        }

        fis.skip(p);

        try {
            int i;
            while ((i = fis.read()) != -1) {
                bos.write(i);
            }
        } catch (Exception e) {
//            e.printStackTrace();
        } finally {
            bos.flush();
            fis.close();
            fos.close();
            bos.close();
        }
    }

    /**
     * 文件下载
     *
     * @param request          request
     * @param response         response
     * @param filePath         文件路径
     * @param originalFileName 显示文件名
     * @param isOnLine         是否在线打开(暂未实现)
     * @throws Exception .
     */
    public static void download(HttpServletRequest request, HttpServletResponse response, String filePath, String originalFileName, Boolean isOnLine) throws Exception {
        File file = new File(filePath);
        if (!file.exists()) {
            response.sendError(404, "File not found!");
            return;
        }
        String fileName = file.getName();
        if (originalFileName != null) {
            fileName = originalFileName;
        }
        setDownloadContentType(request, response, fileName, null, false);

        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        OutputStream fos = null;
        InputStream fis = null;

        try {
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            fos = response.getOutputStream();
            bos = new BufferedOutputStream(fos);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            bos.flush();
            fis.close();
            bis.close();
            fos.close();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置文件下载头
     *
     * @param request           .
     * @param response          .
     * @param fileName          文件名
     * @param encoding          编码格式，空默认为utf-8
     * @param isDownloadSection 是否断点续传
     * @throws UnsupportedEncodingException .
     */
    public static void setDownloadContentType(HttpServletRequest request, HttpServletResponse response, String fileName, String encoding, Boolean isDownloadSection) throws UnsupportedEncodingException {
        if (encoding == null) encoding = "UTF-8";
        response.reset();
        response.setCharacterEncoding(encoding);

        //文件名过长需要截取，否则部分浏览器不支持
        if (fileName.indexOf(".") > 0) {
//            String noExt = fileName.substring(0, fileName.indexOf("."));
//            if (noExt.length() > 15) noExt = noExt.substring(0, 15);
//            String fileExt = fileName.substring(fileName.indexOf(".") + 1);
//            fileName = noExt + "." + fileExt;
            String noExt = FilenameUtils.getBaseName(fileName);
            if (noExt.length() > 15) noExt = noExt.substring(0, 15);
            String fileExt = FilenameUtils.getExtension(fileName);
            fileName = noExt + "." + fileExt;
//            System.out.println("fileName = " + fileName);
        }

        //判断不同浏览器
        String agent = request.getHeader("USER-AGENT");
        if (agent == null) {
            response.setContentType("APPLICATION/OCTET-STREAM");
            String newFileName = URLEncoder.encode(fileName, "UTF-8");  //IE
            response.setHeader("Content-disposition", "attachment;filename=\"" + newFileName + "\"");

        } else {
            Boolean isMozilla = agent.indexOf("Mozilla") > -1;
            Boolean isIE = agent.indexOf("MSIE") > -1;
            Boolean isFirefox = agent.indexOf("Firefox") > -1;
            Boolean isSafari = agent.indexOf("Safari") > -1;
            Boolean isChrome = agent.indexOf("Chrome") > -1;

            if (isMozilla) {   //浏览器下载
                response.setContentType("application/x-act-msdownload;charset=UTF-8");
            } else {
                response.setContentType("APPLICATION/OCTET-STREAM");
            }

            String newFileName = URLEncoder.encode(fileName, "UTF-8");  //IE
            if (isIE) {

            } else if (isFirefox || isSafari) {
                newFileName = new String(fileName.getBytes(encoding), "ISO8859-1"); //Firefox,Safari
            } else if (isChrome) {
                newFileName = new String(Base64.encodeBase64(fileName.getBytes(encoding)));//Chrome
//                newFileName = new String(org.apache.commons.codec.binary.Base64.encodeBase64(fileName.getBytes(encoding)));//Chrome
            }
            response.setHeader("Content-disposition", "attachment;filename=\"" + newFileName + "\"");
        }
    }

}